/**
 *  Copyright (c) 2010 The edtf project.  All rights reserved.
 *
 *  This file is part of edtf (Event Driven Testing Framework).
 *
 *  edtf is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  edtf is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with edtf.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  This software consists of voluntary contributions made by many
 *  individuals.  For exact contribution history, see the revision
 *  history and logs, available at http://code.google.com/p/edtf.
 */
package org.edtf.client;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.edtf.adapter.ws.client.jaxws.MessageIO;
import org.edtf.adapter.ws.client.jaxws.MessageIOService;
import org.xepf.utils.FileUtils;
import org.xepf.utils.Sys;
import org.xepf.utils.Usage;
import org.xepf.utils.Configuration;
import org.xepf.utils.ObjectCreator;
import org.xepf.utils.ConfigurationLoader;
import org.xepf.xml.adapter.NodeSerializer;
import org.xepf.xml.adapter.SimpleXPath;
import org.xepf.xml.adapter.XMLNode;

/**
 * Used for sending events to edtf.server.
 */
public class EdtfClient {

    // todo: generate build information during build
    public static final String appName = "edtf.client";
    public static final String appVersion = "0.0.1";
    public static final String appReleaseDate = "2012-01-03";
    public static NodeSerializer s;

    public static void main(String[] args) {

        System.out.println(Usage.getStartupBanner(appName, appVersion, appReleaseDate));

        if (!hasValidArguments(args)) {
            System.err.println("ERROR: encountered while starting " + appName + ": incorrect arguments.");
            showUsage();
            System.exit(-1);
        }

        String configFilename = args[0];
        String xmlDocFilename = args[1];
        String xPathQuery = args[2];
        String edtfServerWsdlURL = "http://127.0.0.1:7777/edtfserver?wsdl";
        
        if ( args.length == 5 ) {
            edtfServerWsdlURL = args[3];
        }

        Logger.getLogger(EdtfClient.class.getName()).info("XPath 2.0 query: " + xPathQuery);

        String xPathQueryResult = null;

        // "/event-board/events/event[@id='" + i + "']"

        Configuration config = new Configuration();
        try {
            loadConfigFile(config, configFilename);
            String componentsXmlFile = config.getProperty("component.mapper-file");
            loadConfigFile(config, componentsXmlFile);
            ObjectCreator.setConfiguration(config);

            s = (NodeSerializer) ObjectCreator.get("NodeSerializer");

            String xmlDoc = FileUtils.readFile(xmlDocFilename, (int) FileUtils.getFileSize(xmlDocFilename));
            List<XMLNode> nodes = SimpleXPath.query(xmlDoc, xPathQuery);
            xPathQueryResult = s.serialize(nodes);
            System.out.println(xPathQueryResult);

            if (xPathQueryResult.length() > 0) {
                sendEvent(edtfServerWsdlURL, xPathQueryResult);
            }
        } catch (Exception ex) {
            Sys.showExceptionAndExit(ex);
        }

        System.exit(0);
    }

    private static boolean hasValidArguments(String[] args) {
        if (args.length == 3 || args.length == 4) {
            return true;
        }
        return false;
    }

    private static void sendEvent(String edtfServerWsdlUrl, String event) throws Exception {
        URL url = null;
        try {
            URL baseUrl;
            baseUrl = org.edtf.adapter.ws.client.jaxws.MessageIOService.class.getResource(".");
            url = new URL(baseUrl, edtfServerWsdlUrl);
        } catch (MalformedURLException e) {
            Logger.getLogger(EdtfClient.class.getName()).warning("Failed to create URL for the wsdl Location: '" + edtfServerWsdlUrl+ "'.");
            Logger.getLogger(EdtfClient.class.getName()).warning(e.getMessage());
            throw e;
        }
        
        QName qName = new QName("http://jaxws.ws.engine.edtf.org/", "MessageIOService");
        MessageIOService service = new MessageIOService( url, qName);
        MessageIO eventIOProxy = service.getMessageIOPort();

        if (eventIOProxy.write(event)) {
            Logger.getLogger(EdtfClient.class.getName()).fine("Event sent to edtf.server.");
        } else {
            Logger.getLogger(EdtfClient.class.getName()).fine("Event not sent to edtf.server.");
        }
    }

    private static void showUsage() {
        StringBuilder usage = new StringBuilder();
        String lineSeparator = Sys.getProperty("line.separator");
        usage.append("edtf.client can be started using:" + lineSeparator);
        usage.append("  $ edtf.client edtf-client-config events-file xpath-expression" + lineSeparator);
        usage.append("  $ edtf.client edtf-client-config events-file xpath-expression edtf-server-wsdl-url" + lineSeparator);
        usage.append("Example:" + lineSeparator);
        usage.append("  $ edtf.client edtf.client.config.xml events.xml //xtemp:event http://127.0.0.1:7777/edtfserver?wsdl" + lineSeparator);
        System.err.println(usage.toString());
    }

    private static void loadConfigFile(Configuration config, String configFile) throws Exception {
        String configXml = FileUtils.readFile(configFile, (int) FileUtils.getFileSize(configFile));
        ConfigurationLoader configLoader = new ConfigurationLoader(config);
        configLoader.initialize(configXml);
    }
}
